﻿#include "FITKRadiossAdaptorSolverParam.h"
#include "FITKRadiossRadReader.h"
#include "FITKRadiossRadWriter.h"

#include "FITK_Component/FITKRadiossData/FITKRadiossCase.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossSolverSettings.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossResultRequest.h"

#include <QFileInfo>

namespace Radioss
{

    QStringList getKeywordExtraction(QString line)
    {
        //关键字数据提取
        line.trimmed();
        line.remove(QRegExp("^/+"));   // 移除开头的所有'/'
        line.remove(QRegExp("/+$"));   // 移除结尾的所有'/'
        return line.split('/');
    }
    //读取DT数据
    bool readDT(QString line, double& startTime, double& frequency)
    {
        QStringList datas = line.simplified().split(" ");
        if (datas.size() < 2) return false;
        bool ok = false;
        startTime = datas[0].toDouble(&ok);
        if (!ok) return false;
        frequency = datas[1].toDouble(&ok);
        return ok;
    }
    //读取动画节点数据
    bool readVECT(QStringList keywords, QList<FITKRadiossResultRequest::NodalOutputAnimationsType>& typeList)
    {
        auto addType = [&](FITKRadiossResultRequest::NodalOutputAnimationsType type, QList<FITKRadiossResultRequest::NodalOutputAnimationsType>& typeList)
        {
            if (!typeList.contains(type)) return;
            typeList.append(type);
        };

        if (keywords.size() < 3) return false;
        if (keywords[2] == "VEL")
            addType(FITKRadiossResultRequest::NodalOutputAnimationsType::Nodal_Velocity, typeList);
        else if (keywords[2] == "DISP")
            addType(FITKRadiossResultRequest::NodalOutputAnimationsType::Nodal_Displacement, typeList);
        else if (keywords[2] == "ACC")
            addType(FITKRadiossResultRequest::NodalOutputAnimationsType::Nodal_Acceleration, typeList);
        else if (keywords[2] == "CONT")
            addType(FITKRadiossResultRequest::NodalOutputAnimationsType::Nodal_ContactForces, typeList);
        else if (keywords[2] == "FOPT")
            addType(FITKRadiossResultRequest::NodalOutputAnimationsType::Nodal_RigidBodyForcesMoments, typeList);
        else if (keywords[2] == "FINT")
            addType(FITKRadiossResultRequest::NodalOutputAnimationsType::Nodal_InternalForces, typeList);
        else if (keywords[2] == "PCONT")
            addType(FITKRadiossResultRequest::NodalOutputAnimationsType::Nodal_ContactPressure, typeList);
    }
    //读取动画单元数据
    bool readElement(QStringList keywords, QList<FITKRadiossResultRequest::ElementalOutputAnimationsType>& typeList)
    {
        auto addType = [&](FITKRadiossResultRequest::ElementalOutputAnimationsType type, QList<FITKRadiossResultRequest::ElementalOutputAnimationsType>& typeList)
        {
            if (!typeList.contains(type)) return;
            typeList.append(type);
        };

        if (keywords.size() < 3) return false;
        if ("ELEM" == keywords[1])
        {
            if (keywords[2] == "ENER")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_SpecificEnergyDensity, typeList);
            else if (keywords[2] == "EPSP")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_PlasticStrain, typeList);
            else if (keywords[2] == "HOURG")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_HourglassEnergy, typeList);
            else if (keywords[2] == "VONM")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_VonMisesStress, typeList);
            else if (keywords[2] == "P")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_Pressure, typeList);
            else if (keywords[2] == "DENS")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_Density, typeList);
        }
        else if ("BRICK" == keywords[1])
        {
            QString kw4;
            if (keywords.size() > 3)
                kw4 = keywords[3];
            if (keywords[2] == "TENS"  && kw4 == "STRESS")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_Stress, typeList);
            else if (keywords[2] == "TENS"  && kw4 == "STRAIN")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_Strain, typeList);
            else if (keywords[2] == "DAMA")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_SolidDamageOfAll, typeList);

        }
        else if ("SHELL" == keywords[1])
        {
            QString kw4, kw5;
            if (keywords.size() > 3)
                kw4 = keywords[3];
            if (keywords.size() > 4)
                kw5 = keywords[4];
            if (keywords[2] == "TENS"  && kw4 == "STRESS" && kw5 == "ALL")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_StressAllIntegrationPoints, typeList);
            else if (keywords[2] == "TENS"  && kw4 == "STRAIN" && kw5 == "ALL")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_StrainAllIntegrationPoints, typeList);
            else if (keywords[2] == "DAMA")
                addType(FITKRadiossResultRequest::ElementalOutputAnimationsType::Elemental_ShellDamageOfAll, typeList);
        }
        return true;
    } 

    QString FITKRadiossAdaptorSolverParam::getAdaptorClass()
    {
        return "Radioss::FITKRadiossAdaptorSolverParam";
    }

    bool FITKRadiossAdaptorSolverParam::adaptR()
    {
        if (_reader == nullptr) return false;
        bool ok = false;
        //回退一行，读取关键字
        _reader->backLine();
        while (!_reader->atEnd())
        {
            QString line = _reader->readLine();
            if (!line.startsWith("/")) continue;

            //读取打印配置
            if (line.startsWith("/PRINT/"))
            {
                ok = readPrint();
            }
            //读取运行设置
            else if (line.startsWith("/RUN/"))
            {
                ok = readRun();
            }
            //读取并行开关
            else if (line.startsWith("/PARITH/"))
            {
                ok = readParallel();
            }
            else if (line.startsWith("/NEGVOL/"))
            {
                ok = readStopControl();
            }
            //读取动画参数
            else if (line.startsWith("/ANIM/"))
            {
                ok = readAnimationParam();
            }
            else if (line.startsWith("/DT/"))
            {
                ok = readNodeTimeParam();
            }
            else if (line.startsWith("/DT1/"))
            {
                ok = readElemTimeParam();
            }
            else if (line.startsWith("/STOP"))
            {
                ok = readConvergenceCriteriaParam();
            }
            //其他关键字if (line.startsWith("/")) 
            else
            {
                _reader->backLine();
                break;
            }
        }
        return ok;
    }

    bool FITKRadiossAdaptorSolverParam::adaptW()
    {
        _caseData = Radioss::FITKRadiossCase::SafeDownCastFITKRadiossCase(_dataObj);
        if (_writer == nullptr || _caseData == nullptr) return false;
        bool ok = true;

        //写出输出的打印配置
        ok &= writePrint();
        //写出运行的配置
        ok &= writeRun();
        ok &= writeParallel();
        ok &= writeStopControl();
        ok &= writeAnimationParam();
        ok &= writeNodeTimeParam();
        ok &= writeElemTimeParam();

        ok &= writeConvergenceCriteriaParam();

        return ok;
    }

    bool FITKRadiossAdaptorSolverParam::readPrint()
    {
        if (_reader == nullptr) return false;

        _reader->backLine();
        QStringList data = getKeywordExtraction(_reader->readLine());
        if (data.isEmpty()) return false;
        if (data[0].toUpper() != "PRINT") return false;
        //获取输出的打印频率文件参数
        if (data.size() < 3) return false;
        //获取打印输出每个Nprint循环
        int n_print = data[1].toInt();
        //获取几行就会打印一次标题
        int n_line = data[2].toInt();

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writePrint()
    {
        if (_writer == nullptr) return false;

        //默认写出打印配置
        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        *stream << "/PRINT/-100/50" << endl;

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::readRun()
    {
        if (_reader == nullptr || _caseData == nullptr) return false;

        _reader->backLine();
        QStringList data = getKeywordExtraction(_reader->readLine());
        if (data.isEmpty()) return false;
        if (data[0].toUpper() != "RUN") return false;
        //获取运行参数
        if (data.size() < 3) return false;
        //获取运行名称
        QString modelName = data[1];
        //获取运行数
        int run_number = data[2].toInt();
        //获取重启文件标识
        QString res_letter;
        if (data.size() == 4)
            res_letter = data[3].toUpper();
        //获取运行的最终时间
        QString line = _reader->readLine().trimmed();
        double finalTime = line.toDouble();
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverRunExeTimeParam * runExeTimeParam = solverSetting->getRunExeTimeParam();
        if (!runExeTimeParam) return false;
        //设置运行最终时间
        runExeTimeParam->setFinalTime(finalTime);
        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writeRun()
    {
        if (_writer == nullptr || _caseData == nullptr) return false;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverRunExeTimeParam * runExeTimeParam = solverSetting->getRunExeTimeParam();
        if (!runExeTimeParam) return false;
        //获取运行参数
        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        QString fileName = QFileInfo(_writer->getFileName()).baseName();
        if (fileName.size() < 5) return false;
        QString modelName = fileName.left(fileName.size() - 5);
        double finalTime = runExeTimeParam->getFinalTime();
        //写出运行参数
        *stream << QString("/RUN/%1/1").arg(modelName) << endl;
        *stream << QString::number(finalTime) << endl;

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::readParallel()
    {
        if (_reader == nullptr || _caseData == nullptr) return false;

        _reader->backLine();
        QStringList data = getKeywordExtraction(_reader->readLine());
        if (data.isEmpty()) return false;
        if (data[0].toUpper() != "PARITH") return false;
        //获取并行是否开启
        if (data.size() < 2) return false;
        bool isParallel = false;
        if (data[1].toUpper() == "ON")
            isParallel = true;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverComputationControlParam * computationControlParam = solverSetting->getComputationControlParam();
        if (!computationControlParam) return false;

        computationControlParam->setParallelArithmetic(isParallel);

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writeParallel()
    {
        if (_writer == nullptr || _caseData == nullptr) return false;

        //获取并行参数
        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverComputationControlParam * computationControlParam = solverSetting->getComputationControlParam();
        if (!computationControlParam) return false;
        QString parallel = "OFF";
        if (computationControlParam->getParallelArithmetic())
            parallel = "ON";
        *stream << QString("/PARITH/%1").arg(parallel) << endl;

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::readStopControl()
    {
        if (_reader == nullptr || _caseData == nullptr) return false;

        _reader->backLine();
        QStringList data = getKeywordExtraction(_reader->readLine());
        if (data.isEmpty()) return false;
        if (data[0].toUpper() != "NEGVOL") return false;
        //获取并行是否开启
        if (data.size() < 2) return false;
        bool stopComputation = false;
        if (data[1].toUpper() == "STOP")
            stopComputation = true;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverComputationControlParam * computationControlParam = solverSetting->getComputationControlParam();
        if (!computationControlParam) return false;

        computationControlParam->setStopComputationWhenNegativeVolume(stopComputation);

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writeStopControl()
    {
        if (_writer == nullptr || _caseData == nullptr) return false;

        //获取并行参数
        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverComputationControlParam * computationControlParam = solverSetting->getComputationControlParam();
        if (!computationControlParam) return false;
        QString parallel = "SMSTR";
        if (computationControlParam->getStopComputationWhenNegativeVolume())
            parallel = "STOP";
        *stream << QString("/NEGVOL/%1").arg(parallel) << endl;

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::readAnimationParam()
    {
        if (_reader == nullptr || _caseData == nullptr) return false;

        //获取求解设置数据
        FITKRadiossResultRequest * resultRequest = _caseData->getResultRequest();
        if (!resultRequest) return false;
        QList<FITKRadiossResultRequest::NodalOutputAnimationsType> nodalType = resultRequest->getNodalOutputAnim();
        QList<FITKRadiossResultRequest::ElementalOutputAnimationsType> elementType = resultRequest->getElementalOutputAnim();
        //回退一行，读取关键字
        _reader->backLine();
        while (!_reader->atEnd())
        {
            QString line = _reader->readLine();
            if (!line.startsWith("/")) continue;
            if (!line.startsWith("/ANIM"))
            {
                _reader->backLine();
                break;
            }
            QStringList keywords = getKeywordExtraction(line);
            //获取动画的关键字
            if (keywords.size() < 2) continue;
            QString kw = keywords[1];
            if (kw == "DT")
            {
                double startTime = 0.0, frequency = 0.0;
                readDT(_reader->readLine(), startTime, frequency);
                resultRequest->setStartTime(startTime);
                resultRequest->setFrequency(frequency);
            }
            else if (kw == "VECT")
            {
                readVECT(keywords, nodalType);
            }
            else if (kw == "ELEM" || kw == "SHELL" || kw == "BRICK")
            {
                readElement(keywords, elementType);
            }
        }
        resultRequest->setNodalOutputAnim(nodalType);
        resultRequest->setElementalOutputAnim(elementType);
        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writeAnimationParam()
    {
        if (_writer == nullptr || _caseData == nullptr) return false;

        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        //获取求解设置数据
        FITKRadiossResultRequest * resultRequest = _caseData->getResultRequest();
        if (!resultRequest) return false;
        QList<FITKRadiossResultRequest::NodalOutputAnimationsType> nodalType = resultRequest->getNodalOutputAnim();
        QList<FITKRadiossResultRequest::ElementalOutputAnimationsType> elementType = resultRequest->getElementalOutputAnim();
        double startTime = resultRequest->getStartTime();
        double frequency = resultRequest->getFrequency();

        //写出动画开始时间和频率
        *stream << "/ANIM/DT" << endl;
        *stream << QString("%1     %2").arg(startTime).arg(frequency) << endl;
        //写出节点动画类型
        for (FITKRadiossResultRequest::NodalOutputAnimationsType type : nodalType)
        {
            switch (type)
            {
            case Radioss::FITKRadiossResultRequest::Nodal_Displacement: *stream << "/ANIM/VECT/DISP" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Nodal_Velocity: *stream << "/ANIM/VECT/VEL" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Nodal_Acceleration: *stream << "/ANIM/VECT/ACC" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Nodal_ContactForces: *stream << "/ANIM/VECT/CONT" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Nodal_RigidBodyForcesMoments: *stream << "/ANIM/VECT/FOPT" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Nodal_InternalForces: *stream << "/ANIM/VECT/FINT" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Nodal_ContactPressure: *stream << "/ANIM/VECT/PCONT" << endl;
                break;
            default:
                break;
            }
        }
        //写出单元动画类型
        for (FITKRadiossResultRequest::ElementalOutputAnimationsType type : elementType)
        {
            switch (type)
            {
            case Radioss::FITKRadiossResultRequest::Elemental_Stress: *stream << "/ANIM/BRICK/TENS/STRESS" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_StressAllIntegrationPoints: *stream << "/ANIM/SHELL/TENS/STRESS/ALL" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_Strain: *stream << "/ANIM/BRICK/TENS/STRAIN" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_StrainAllIntegrationPoints: *stream << "/ANIM/SHELL/TENS/STRAIN/ALL" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_SpecificEnergyDensity: *stream << "/ANIM/ELEM/ENER" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_PlasticStrain: *stream << "/ANIM/ELEM/EPSP" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_HourglassEnergy: *stream << "/ANIM/ELEM/HOURG" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_VonMisesStress: *stream << "/ANIM/ELEM/VONM" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_Pressure: *stream << "/ANIM/ELEM/P" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_Density: *stream << "/ANIM/ELEM/DENS" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_ShellDamageOfAll: *stream << "/ANIM/SHELL/DAMA" << endl;
                break;
            case Radioss::FITKRadiossResultRequest::Elemental_SolidDamageOfAll: *stream << "/ANIM/BRICK/DAMA" << endl;
                break;
            default:
                break;
            }
        }
        return true;
    }

    bool FITKRadiossAdaptorSolverParam::readNodeTimeParam()
    {
        if (_reader == nullptr || _caseData == nullptr) return false;
        _reader->backLine();
        QStringList data = getKeywordExtraction(_reader->readLine());
        if (data.isEmpty()) return false;
        if (data[0].toUpper() != "DT") return false;

        if (data.size() < 2) return false;
        //获取类型
        if (data[1].toUpper() != "NODA") return false;
        FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStepControlType type = FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStepControlType::NodalTimeStep_SolverDefault;
        if (data.size() > 2)
        {
            if (data[2].toUpper() == "CST")
                type = FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStepControlType::NodalTimeStep_CST;
            else if (data[2].toUpper() == "SET")
                type = FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStepControlType::NodalTimeStep_SET;
            else if (data[2].toUpper() == "STOP")
                type = FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStepControlType::NodalTimeStep_STOP;
        }
        
        //获取参数
        QString line = _reader->readLine();
        data = line.simplified().split(" ");
        double minTimeStep = 0.0, scaleFactor = 0.0, initAddMassRatio = 0.0;
        if (data.size() > 0)
            scaleFactor = data[0].toDouble();
        if (data.size() > 1)
            minTimeStep = data[1].toDouble();
        if (data.size() > 2)
            initAddMassRatio = data[2].toDouble();

        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverNodalTimeStepControlParam * nodalTimeParam = solverSetting->getNodalTimeStepControlParam();
        if (!nodalTimeParam) return false;
        nodalTimeParam->setTimeStepControlType(type);
        nodalTimeParam->setMinimumTimeStep(minTimeStep);
        nodalTimeParam->setScaleFactor(scaleFactor);
        nodalTimeParam->setInitialAddMassRatio(initAddMassRatio);

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writeNodeTimeParam()
    {
        if (_writer == nullptr || _caseData == nullptr) return false;

        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverNodalTimeStepControlParam * nodalTimeParam = solverSetting->getNodalTimeStepControlParam();
        if (!nodalTimeParam) return false;
        FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStepControlType type = nodalTimeParam->getTimeStepControlType();
        double minTimeStep = nodalTimeParam->getMinimumTimeStep(), scaleFactor = nodalTimeParam->getScaleFactor(), initAddMassRatio = nodalTimeParam->getInitialAddMassRatio();

        //写出节点时间步参数
        switch (type)
        {
        case Radioss::FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStep_SolverDefault: *stream << "/DT/NODA/" << endl;
            break;
        case Radioss::FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStep_CST: *stream << "/DT/NODA/CST" << endl;
            break;
        case Radioss::FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStep_SET: *stream << "/DT/NODA/SET" << endl;
            break;
        case Radioss::FITKRadiossSolverNodalTimeStepControlParam::NodalTimeStep_STOP: *stream << "/DT/NODA/STOP" << endl;
            break;
        default:
            break;
        }

        *stream << QString("%1  %2  %3").arg(scaleFactor).arg(minTimeStep).arg(initAddMassRatio) << endl;
        //写出高阶四面体的计算步时间改进
        *stream << QString("/DT1TET10") << endl;
        return true;
    }

    bool FITKRadiossAdaptorSolverParam::readElemTimeParam()
    {
        if (_reader == nullptr || _caseData == nullptr) return false;
        _reader->backLine();
        QStringList data = getKeywordExtraction(_reader->readLine());
        if (data.isEmpty()) return false;
        if (data[0].toUpper() != "DT1") return false;

        if (data.size() < 2) return false;
        //获取类型
        int flag = 0;
        if (data[1].toUpper() != "BRICK") return false;
        FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStepControlType type = FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStepControlType::ElementalTimeStep_SolverDefault;
        if (data.size() > 2)
        {
            if (data[2].toUpper() == "CST")
                type = FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStepControlType::ElementalTimeStep_CST;
            else if (data[2].toUpper() == "DEL")
                type = FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStepControlType::ElementalTimeStep_DEL;
            else if (data[2].toUpper() == "STOP")
                type = FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStepControlType::ElementalTimeStep_STOP;
        }
        if (data.size() > 3)
            flag = data[3].toInt();
        
        //获取参数
        QString line = _reader->readLine();
        data = line.simplified().split(" ");
        double minTimeStep = 0.0, scaleFactor = 0.0;
        if (data.size() > 0)
            minTimeStep = data[0].toDouble();
        if (data.size() > 1)
            scaleFactor = data[1].toDouble();
        bool numberOfAddCards = false;
        double minAspectRatio = 0.0, minVolumeRatio = 0.0;
        if (type == FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStepControlType::ElementalTimeStep_CST && flag > 0)
        {
            numberOfAddCards = true;
            line = _reader->readLine();
            data = line.simplified().split(" ");
            if (data.size() > 0)
                minAspectRatio = data[0].toDouble();
            if (data.size() > 1)
                minVolumeRatio = data[1].toDouble();
        }

        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverElementalTimeStepControlParam * elementalTimeParam = solverSetting->getElementalTimeStepControlParam();
        if (!elementalTimeParam) return false;
        elementalTimeParam->setTimeStepControlType(type);
        elementalTimeParam->setMinimumTimeStep(minTimeStep);
        elementalTimeParam->setScaleFactor(scaleFactor);
        elementalTimeParam->setNumberOfAddCards(numberOfAddCards);
        elementalTimeParam->setMinAspectRatio(minAspectRatio);
        elementalTimeParam->setMinVolumeRatio(minVolumeRatio);

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writeElemTimeParam()
    {
        if (_writer == nullptr || _caseData == nullptr) return false;

        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverElementalTimeStepControlParam * elementalTimeParam = solverSetting->getElementalTimeStepControlParam();
        if (!elementalTimeParam) return false;
        FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStepControlType type = elementalTimeParam->getTimeStepControlType();
        double minTimeStep = elementalTimeParam->getMinimumTimeStep(), scaleFactor = elementalTimeParam->getScaleFactor();
        bool numberOfAddCards = elementalTimeParam->getNumberOfAddCards();
        double minAspectRatio = elementalTimeParam->getMinAspectRatio(), minVolumeRatio = elementalTimeParam->getMinVolumeRatio();

        //写出节点时间步参数
        switch (type)
        {
        case Radioss::FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStep_SolverDefault: *stream << "/DT1/BRICK/" << endl;
            break;
        case Radioss::FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStep_CST: 
        {
            if (numberOfAddCards)
                *stream << "/DT1/BRICK/CST/1" << endl;
            else
                *stream << "/DT1/BRICK/CST" << endl;
            break;
        }
        case Radioss::FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStep_DEL: *stream << "/DT1/BRICK/DEL" << endl;
            break;
        case Radioss::FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStep_STOP: *stream << "/DT1/BRICK/STOP" << endl;
            break;
        default:
            break;
        }


        *stream << QString("%1  %2").arg(minTimeStep).arg(scaleFactor) << endl;
        if (type == Radioss::FITKRadiossSolverElementalTimeStepControlParam::ElementalTimeStep_CST && numberOfAddCards)
            *stream << QString("%1  %2").arg(minAspectRatio).arg(minVolumeRatio) << endl;
        return true;
    }

    bool FITKRadiossAdaptorSolverParam::readConvergenceCriteriaParam()
    {
        if (_reader == nullptr || _caseData == nullptr) return false;
        _reader->backLine();
        QStringList data = getKeywordExtraction(_reader->readLine());
        if (data.isEmpty()) return false;
        if (data[0].toUpper() != "STOP") return false;

        //获取参数
        QString line = _reader->readLine();
        data = line.simplified().split(" ");
        double energyErrorRatio = 0.0, totalMassRatio = 0.0, nodalMassRatio = 0.0;
        bool writeTimeHistoryFile = false, writeAnimationFile = false, energyError = false;
        if (data.size() > 0)
            energyErrorRatio = data[0].toDouble();
        if (data.size() > 1)
            totalMassRatio = data[1].toDouble();
        if (data.size() > 2)
            nodalMassRatio = data[2].toDouble();
        if (data.size() > 3)
            writeTimeHistoryFile = data[3].toInt() > 0 ? true : false;
        if (data.size() > 4)
            writeAnimationFile = data[4].toInt() > 0 ? true : false;
        if (data.size() > 5)
            energyError = data[5].toInt() > 0 ? true : false;

        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverConvergenceCriteriaParam * convergenceCriteriaParam = solverSetting->getConvergenceCriteriaParam();
        if (!convergenceCriteriaParam) return false;
        convergenceCriteriaParam->setStopComputation(true);
        convergenceCriteriaParam->setEnergyErrorRatio(energyErrorRatio);
        convergenceCriteriaParam->setTotalMassRatio(totalMassRatio);
        convergenceCriteriaParam->setNodalMassRatio(nodalMassRatio);
        convergenceCriteriaParam->setWriteTimeHistoryFile(writeTimeHistoryFile);
        convergenceCriteriaParam->setWriteAnimationFile(writeAnimationFile);
        convergenceCriteriaParam->setEnergyError(energyError);

        return true;
    }

    bool FITKRadiossAdaptorSolverParam::writeConvergenceCriteriaParam()
    {
        if (_writer == nullptr || _caseData == nullptr) return false;

        QTextStream* stream = _writer->getStream();
        if (!stream) return false;
        //获取求解设置数据
        FITKRadiossSolverSettings * solverSetting = _caseData->getSolverSettings();
        if (!solverSetting) return false;
        FITKRadiossSolverConvergenceCriteriaParam * convergenceCriteriaParam = solverSetting->getConvergenceCriteriaParam();
        if (!convergenceCriteriaParam) return false;
        if (!convergenceCriteriaParam->getStopComputation()) return true;
        //获取参数数据
        double energyErrorRatio = convergenceCriteriaParam->getEnergyErrorRatio(), totalMassRatio = convergenceCriteriaParam->getTotalMassRatio(), nodalMassRatio = convergenceCriteriaParam->getNodalMassRatio();
        bool writeTimeHistoryFile = convergenceCriteriaParam->getWriteTimeHistoryFile(), writeAnimationFile = convergenceCriteriaParam->getWriteAnimationFile(), energyError = convergenceCriteriaParam->getEnergyError();

        *stream << QString("/STOP") << endl;
        *stream << QString("%1  %2  %3  %4  %5  %6").arg(energyErrorRatio).arg(totalMassRatio).arg(nodalMassRatio).arg(int(writeTimeHistoryFile)).arg(int(writeAnimationFile)).arg(int(energyError)) << endl;

        return true;
    }

}
